/*
 * $Id: InetAddress.h,v 1.8 2006-04-04 11:45:40 bacon Exp $
 */

#ifndef _XPP_NET_INETADDRESS_CLASS_
#define _XPP_NET_INETADDRESS_CLASS_

#include <xpp/net/Address.h>
#include <xpp/bas/String.h>

#ifndef _WIN32
	#include <netdb.h>
	#include <arpa/inet.h>
	#include <netinet/in.h>
#endif

#if defined(__linux) && !defined(XP_HAVE_SS_FAMILY)
	#define ss_family __ss_family
#endif

namespace xpp
{
	namespace net
	{

		class InetAddress: public Address
		{
		public:
			InetAddress ();
			InetAddress (int family, int type);
			InetAddress (const InetAddress& adr);
			InetAddress (const struct sockaddr_storage& adr);
			InetAddress (const struct sockaddr_in& adr);
			InetAddress (const struct sockaddr_in6& adr);

			// family
			enum {
				V0 = AF_UNSPEC,
				V4 = AF_INET,
				V6 = AF_INET6
			};

			enum 
			{
				MAX_HOST_LEN    = NI_MAXHOST,
				MAX_SERVICE_LEN = NI_MAXSERV
			};
	
			virtual InetAddress& operator= (const InetAddress& adr);
			virtual InetAddress& operator= (const struct sockaddr_storage& adr);
			virtual InetAddress& operator= (const struct sockaddr_in& adr);
			virtual InetAddress& operator= (const struct sockaddr_in6& adr);

			virtual bool operator== (const InetAddress& adr) const;
			virtual bool operator!= (const InetAddress& adr) const;

			bool hasEqualFamily (const InetAddress& addr) const;
			bool hasEqualHost (const InetAddress& addr) const;
			bool hasEqualService (const InetAddress& addr) const;

			virtual int family () const
			{
				return address_storage.ss_family;
			}

			virtual int type () const
			{
				return address_type;
			}

			virtual addr_t* storage () const
			{
				return (addr_t*)&address_storage;
			}

			virtual len_t storageSize () const;

			virtual bool isLoopBack  () const;
			virtual bool isAnyLocal  () const;
			/*virtual bool isLinkLocal () const;*/
			/*virtual bool isSiteLocal () const;*/
			/*virtual bool isMulticast () const;*/

			virtual int getNumericHost (xp_char_t* buf, xp_size_t size) const;
			virtual int getNumericService (
				xp_char_t* buf, xp_size_t size) const;

			virtual int getHostName (xp_char_t* buf, xp_size_t size) const;
			virtual int getServiceName (xp_char_t* buf, xp_size_t size) const;

			virtual xpp::bas::String numericHost    () const;
			virtual xpp::bas::String numericService () const;
			virtual xpp::bas::String hostName       () const;
			virtual xpp::bas::String serviceName    () const;

			static int resolve (
				const xp_char_t* service, InetAddress* address);
			static int resolve (
				const xp_char_t* service, const xp_char_t* host, 
				InetAddress* address);

		protected:
			struct sockaddr_storage address_storage;
			int address_type;

			int resolve_address (
				const xp_char_t* service, const xp_char_t* host, 
				int family, int type, int* errnum);
		};

	}
}

#endif
